package org.hako.recite.word.words.impl;

import static org.hako.recite.word.test.WordTestProfile.RANDOM_MODE_ENTIRE;
import static org.hako.recite.word.test.WordTestProfile.RANDOM_MODE_PART;

import org.hako.recite.word.test.WordTestProfile;
import org.hako.recite.word.words.IndexHandler;

/**
 * Factory of {@link IndexHandler}.
 * 
 * @since 0.4.2
 * @author <a href="mailto:xnnyygn@gmail.com">xnnyygn</a>
 */
public class IndexHandlerFactory {

	/**
	 * Create index handler.
	 * 
	 * @param wordCount
	 * @param profile
	 * @return
	 */
	public IndexHandler create(int wordCount, WordTestProfile profile)
			throws IllegalArgumentException {
		if (profile.isRandom()) {
			switch (profile.getRandomMode()) {
			case RANDOM_MODE_PART:
				return createPartRandomIndexHandler(profile, wordCount);
			case RANDOM_MODE_ENTIRE:
				return createEntireRandomIndexHandler(profile, wordCount);
			default:
				throw new IllegalArgumentException("Illegal mode ["
						+ profile.getRandomMode() + "]");
			}
		}
		return new DirectIndexHandler();
	}

	/**
	 * Create entire random index handler.
	 * 
	 * @param profile
	 * @param wordCount
	 * @return
	 * @throws IllegalArgumentException
	 */
	public IndexHandler createEntireRandomIndexHandler(WordTestProfile profile,
			int wordCount) throws IllegalArgumentException {
		int testWordRangeStart = profile.getWordRangeStart();
		int testWordRangeEnd = profile.getWordRangeEnd();
		if (testWordRangeStart > wordCount
				|| testWordRangeStart >= testWordRangeEnd) {
			throw new IllegalArgumentException("Illegal range start ["
					+ testWordRangeStart + "]");
		}
		if (testWordRangeEnd > wordCount) {
			testWordRangeEnd = wordCount;
			profile.setWordRangeEnd(testWordRangeEnd);
		}
		int testWordLimit = profile.getWordLimit();
		int minOfCountAndRange = Math.min(
				testWordRangeEnd - testWordRangeStart, wordCount);
		if (testWordLimit > minOfCountAndRange) {
			testWordLimit = minOfCountAndRange;
			profile.setWordLimit(testWordLimit);
		}
		return new EntireRandomIndexHandler(testWordLimit, testWordRangeStart,
				testWordRangeEnd);
	}

	/**
	 * Create part random index handler.
	 * 
	 * @param profile
	 * @param wordCount
	 * @return
	 * @throws IllegalArgumentException
	 */
	private IndexHandler createPartRandomIndexHandler(WordTestProfile profile,
			int wordCount) throws IllegalArgumentException {
		int testWordOffset = profile.getWordOffset();
		if (testWordOffset >= wordCount) {
			throw new IllegalArgumentException("Illegal offset ["
					+ testWordOffset + "]");
		}
		int testWordLimit = profile.getWordLimit();
		if (testWordOffset + testWordLimit > wordCount) {
			testWordLimit = wordCount - testWordOffset;
			profile.setWordLimit(testWordLimit);
		}
		return new PartRandomIndexHandler(wordCount, testWordOffset,
				testWordLimit);
	}
}
